﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using EPiServer;
using EPiServer.Core;
using EPiServer.DataAccess;
using EPiServer.Security;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TemplateFoundation.Configuration;
using TemplateFoundation.Core;
using TemplateFoundation.PageTypes;
using TemplateFoundation.Tests.Environment;

namespace TemplateFoundation.Tests.UnitTests.Core
{
    [TestClass]
    public class PageFactoryPersons
    {
        [TestMethod]
        public void TestPersonPageCacheIsUpdatedWhenPersonPageIsMoved()
        {
            Settings.Instance.ContactsContainer = null;

            // Create person page
            var person = PageStructure.CreatePersonPage("Ted Nyberg");

            // Get person from cache
            var persons = PageFactory.Instance.GetPersons().Where(p => p.PageName == "Ted Nyberg");

            Assert.IsTrue(persons.Count()==1, "For some reason there was not exactly one (1) 'Ted Nyberg' person page");

            // Move page
            var newTarget = PageStructure.CreateStandardPages("New target", PageReference.StartPage, 1);
            DataFactory.Instance.Move(person.PageLink, newTarget[0].PageLink, AccessLevel.NoAccess, AccessLevel.NoAccess);
            
            // Get persons from cache again to verify parent link was updated
            persons = PageFactory.Instance.GetPersons().Where(p => p.PageName == "Ted Nyberg");

            Assert.IsTrue(persons.First().ParentLink.ID == newTarget[0].PageLink.ID, "Persons cache was not updated when person page was moved");            
        }

        [TestMethod]
        public void TestPersonsAreOnlyRetrievedUnderContactsContainerIfSpecified()
        {
            var persons = new PageDataCollection();

            // Create person pages outside container
            Settings.Instance.ContactsContainer = null;
            for (int i=0; i<2; i++)
            {
                persons.Add(PageStructure.CreatePersonPage("Some person " + i));   
            }

            // Create person pages under container
            var container = PageStructure.CreateStandardPages("Persons container", PageReference.RootPage, 1)[0];
            Settings.Instance.ContactsContainer = container.PageLink;
            for (int i=0; i<2; i++)
            {
                persons.Add(PageStructure.CreatePersonPage("Some person " + i));
            }

            Assert.IsTrue(PageFactory.Instance.GetPersons().Count==2, "Expected 2 person pages");
        }

        [TestMethod]
        public void TestPersonsAreRetrievedFromEntireSiteIfContactsContainerIsNotSet()
        {
            Settings.Instance.ContactsContainer = null;

            var container = PageStructure.CreateStandardPages("Persons container", PageReference.RootPage, 1)[0];

            var persons = new PageDataCollection();

            // Create person pages
            for (int i=0; i<4; i++)
            {
                persons.Add(PageStructure.CreatePersonPage("Contact outside container " + i));
            }

            DataFactory.Instance.Move(persons[1].PageLink, container.PageLink, AccessLevel.NoAccess, AccessLevel.NoAccess);
            DataFactory.Instance.Move(persons[2].PageLink, container.PageLink, AccessLevel.NoAccess, AccessLevel.NoAccess);

            Assert.IsTrue(PageFactory.Instance.GetPersons().Count==4, "Expected 4 person pages");
        }

        [TestMethod]
        public void TestPersonPageCacheIsUpdatedWhenPersonPageIsUpdated()
        {
            Settings.Instance.ContactsContainer = null;

            const string ORIGINAL_NAME = "Ted Nyberg original";
            const string UPDATED_NAME = "Ted Nyberg updated";

            // Create person page
            var person = PageStructure.CreatePersonPage(ORIGINAL_NAME);

            // Get person from cache
            var persons = PageFactory.Instance.GetPersons().Where(p => p.PageName == ORIGINAL_NAME);

            Assert.IsTrue(persons.Count()==1, "For some reason there was not exactly one (1) '" + ORIGINAL_NAME + "' person page");

            // Update page
            var clone = (PersonPageBase) person.CreateWritableClone();
            clone.PageName = UPDATED_NAME;
            DataFactory.Instance.Save(clone, SaveAction.Publish, AccessLevel.NoAccess);

            // Ensure previous version is no longer in the cache
            persons = PageFactory.Instance.GetPersons().Where(p => p.PageName == ORIGINAL_NAME);
            Assert.IsTrue(persons.Count()==0, "The cache still contains a '" + ORIGINAL_NAME + "' person page");
            
            // Ensure updated person page is in the cache
            persons = PageFactory.Instance.GetPersons().Where(p => p.PageName == UPDATED_NAME);
            Assert.IsTrue(persons.Count()==1, "The cache does not contain a '" + UPDATED_NAME + "'");
        }

        [TestMethod]
        public void TestPersonPagesAreSortedAlphabeticallyAscendingOrderWithNoContactsContainerSet()
        {
            TestPersonPagesAreSortedAlphabeticallyAscendingOrder(false);
        }

        [TestMethod]
        public void TestPersonPagesAreSortedAlphabeticallyAscendingOrderWithContactsContainerSet()
        {
            TestPersonPagesAreSortedAlphabeticallyAscendingOrder(true);
        }

        public void TestPersonPagesAreSortedAlphabeticallyAscendingOrder(bool useContactsContainer)
        {
            PageStructure.EmptyWebsite();

            if (useContactsContainer)
            {
                Settings.Instance.ContactsContainer = PageStructure.CreateStandardPages("Contacts container for sort test", PageReference.RootPage, 1)[0].PageLink;
            }
            else
            {
                Settings.Instance.ContactsContainer = null;    
            }

            var persons = new PageDataCollection();

            var names = new[]
                            {
                                "Erik Eriksson", 
                                "Östen Örtgren",
                                "Thomas Tand", 
                                "Ärliga Sven", 
                                "Anna Andersson",
                                "Ågren Efter"
                            };

            foreach (var name in names)
            {
                persons.Add(PageStructure.CreatePersonPage(name));
            }

            var retrievedPersons = PageFactory.Instance.GetPersons();

            Assert.IsTrue(retrievedPersons[0].PageName.Substring(0, 1).Equals("a", StringComparison.OrdinalIgnoreCase), "Expected 'a' in sort order");
            Assert.IsTrue(retrievedPersons[1].PageName.Substring(0, 1).Equals("e", StringComparison.OrdinalIgnoreCase), "Expected 'e' in sort order");
            Assert.IsTrue(retrievedPersons[2].PageName.Substring(0, 1).Equals("t", StringComparison.OrdinalIgnoreCase), "Expected 't' in sort order");
            Assert.IsTrue(retrievedPersons[3].PageName.Substring(0, 1).Equals("å", StringComparison.OrdinalIgnoreCase), "Expected 'å' in sort order");
            Assert.IsTrue(retrievedPersons[4].PageName.Substring(0, 1).Equals("ä", StringComparison.OrdinalIgnoreCase), "Expected 'ä' in sort order");
            Assert.IsTrue(retrievedPersons[5].PageName.Substring(0, 1).Equals("ö", StringComparison.OrdinalIgnoreCase), "Expected 'ö' in sort order");
        }
    }
}
